package coc.core.url;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import coo.base.constants.Chars;
import coo.base.util.StringUtils;

/**
 * 网页链接验证器。
 */
public class UrlValidator {
	private List<String> endsWith = new ArrayList<String>();
	private List<String> notEndsWith = new ArrayList<String>();
	private List<String> startsWith = new ArrayList<String>();
	private List<String> notStartsWith = new ArrayList<String>();
	private List<String> contains = new ArrayList<String>();
	private List<String> notContains = new ArrayList<String>();
	private List<String> matches = new ArrayList<String>();
	private List<String> notMatches = new ArrayList<String>();

	/**
	 * 构造方法。
	 */
	public UrlValidator() {
		startsWith("http://,https://");
		notEndsWith(".gif,.GIF,.doc,.DOC,.pdf,.PDF,.bat,.exe,.BAT,.dll,.DLL,.jpg,.JPG,.jpeg,.JPEG,.png,.PNG,.bmp,.BMP,exe.EXE,.rar,.RAR,.xml,.XML,.mp3,.MP3,.xls,.XLS,.swf,.SWF,.zip,.ZIP,.wmv,.WMV,.mpg,.MPG,rm,RM,.ppt,.PPT,.apk,.APK");
		notContains("#");
	}

	/**
	 * 设置基础链接。验证器将以基础链接中的域名作为必须包含条件进行验证。
	 * 
	 * @param baseUrl
	 *            基础链接
	 */
	public void base(String baseUrl) {
		if (contains.isEmpty()) {
			String domain = StringUtils.substringAfter(baseUrl, "//");
			domain = StringUtils.substringBefore(domain, "/");
			contains(domain);
		}
	}

	/**
	 * 新增以指定字符串结尾的条件。
	 * 
	 * @param expressions
	 *            结尾字符串,多个可用“,”分隔
	 */
	public void endsWith(String expressions) {
		setExpressions(expressions, endsWith);
	}

	/**
	 * 新增不以指定字符串结尾的条件。
	 * 
	 * @param expressions
	 *            结尾字符串,多个可用“,”分隔
	 */
	public void notEndsWith(String expressions) {
		setExpressions(expressions, notEndsWith);
	}

	/**
	 * 新增以指定字符串开头的条件。
	 * 
	 * @param expressions
	 *            开头字符串,多个可用“,”分隔
	 */
	public void startsWith(String expressions) {
		setExpressions(expressions, startsWith);
	}

	/**
	 * 新增不以指定字符串开头的条件。
	 * 
	 * @param expressions
	 *            开头字符串,多个可用“,”分隔
	 */
	public void notStartsWith(String expressions) {
		setExpressions(expressions, notStartsWith);
	}

	/**
	 * 新增包含指定字符串的条件。
	 * 
	 * @param expressions
	 *            包含字符串,多个可用“,”分隔
	 */
	public void contains(String expressions) {
		setExpressions(expressions, contains);
	}

	/**
	 * 新增不包含指定字符串的条件。
	 * 
	 * @param expressions
	 *            不包含字符串,多个可用“,”分隔
	 */
	public void notContains(String expressions) {
		setExpressions(expressions, notContains);
	}

	/**
	 * 新增匹配正则表达式字符串的条件。
	 * 
	 * @param expressions
	 *            正则表达式,多个可用“,”分隔
	 */
	public void matches(String expressions) {
		setExpressions(expressions, matches);
	}

	/**
	 * 新增不匹配正则表达式字符串的条件。
	 * 
	 * @param expressions
	 *            正则表达式,多个可用“,”分隔
	 */
	public void notMatches(String expressions) {
		setExpressions(expressions, notMatches);
	}

	/**
	 * 验证指定URL是否满足条件。
	 * 
	 * @param url
	 *            URL
	 * @return 如果URL满足条件返回true，否则返回false。
	 */
	public Boolean validate(String url) {
		return validateEndsWith(url) && validateNotEndsWith(url)
				&& validateStartsWith(url) && validateNotStartsWith(url)
				&& validateContains(url) && validateNotContains(url)
				&& validateMatches(url) && validateNotMatches(url);
	}

	/**
	 * 清空所有验证条件。
	 */
	public void clear() {
		endsWith("");
		notEndsWith("");
		startsWith("");
		notStartsWith("");
		contains("");
		notContains("");
	}

	/**
	 * 设置表达式字符串的条件。
	 * 
	 * @param expressions
	 *            表达式字符串
	 * @param toList
	 *            对应条件列表
	 */
	private void setExpressions(String expressions, List<String> toList) {
		if (StringUtils.isBlank(expressions)) {
			toList.clear();
			return;
		}
		toList.addAll(Arrays.asList(expressions.split(Chars.COMMA)));
	}

	/**
	 * 验证是否满足结尾条件。
	 * 
	 * @param url
	 *            URL
	 * @return 满足结尾条件返回true，否则返回false。
	 */
	private Boolean validateEndsWith(String url) {
		if (!endsWith.isEmpty()) {
			for (String expression : endsWith) {
				if (url.endsWith(expression)) {
					return true;
				}
			}
			return false;
		}
		return true;
	}

	/**
	 * 验证是否满足不以结尾条件。
	 * 
	 * @param url
	 *            URL
	 * @return 满足不以结尾条件返回true，否则返回false。
	 */
	private Boolean validateNotEndsWith(String url) {
		if (!notEndsWith.isEmpty()) {
			for (String expression : notEndsWith) {
				if (url.endsWith(expression)) {
					return false;
				}
			}
			return true;
		}
		return true;
	}

	/**
	 * 验证是否满足开头条件。
	 * 
	 * @param url
	 *            URL
	 * @return 满足开头条件返回true，否则返回false。
	 */
	private Boolean validateStartsWith(String url) {
		if (!startsWith.isEmpty()) {
			for (String expression : startsWith) {
				if (url.startsWith(expression)) {
					return true;
				}
			}
			return false;
		}
		return true;
	}

	/**
	 * 验证是否满足不以开头条件。
	 * 
	 * @param url
	 *            URL
	 * @return 满足不以开头条件返回true，否则返回false。
	 */
	private Boolean validateNotStartsWith(String url) {
		if (!notStartsWith.isEmpty()) {
			for (String expression : notStartsWith) {
				if (url.startsWith(expression)) {
					return false;
				}
			}
			return true;
		}
		return true;
	}

	/**
	 * 验证是否满足包含条件。
	 * 
	 * @param url
	 *            URL
	 * @return 满足包含条件返回true，否则返回false。
	 */
	private Boolean validateContains(String url) {
		if (!contains.isEmpty()) {
			for (String expression : contains) {
				if (url.contains(expression)) {
					return true;
				}
			}
			return false;
		}
		return true;
	}

	/**
	 * 验证是否满足不包含条件。
	 * 
	 * @param url
	 *            URL
	 * @return 满足不包含条件返回true，否则返回false。
	 */
	private Boolean validateNotContains(String url) {
		if (!notContains.isEmpty()) {
			for (String expression : notContains) {
				if (url.contains(expression)) {
					return false;
				}
			}
			return true;
		}
		return true;
	}

	/**
	 * 验证是否满足匹配条件。
	 * 
	 * @param url
	 *            URL
	 * @return 如果满足匹配条件返回true，否则返回false。
	 */
	private Boolean validateMatches(String url) {
		if (!matches.isEmpty()) {
			for (String expression : matches) {
				if (url.matches(expression)) {
					return true;
				}
			}
			return false;
		}
		return true;
	}

	/**
	 * 验证是否满足不匹配条件。
	 * 
	 * @param url
	 *            URL
	 * @return 如果满足不匹配条件返回true，否则返回false。
	 */
	private Boolean validateNotMatches(String url) {
		if (!notMatches.isEmpty()) {
			for (String expression : notMatches) {
				if (url.matches(expression)) {
					return false;
				}
			}
			return true;
		}
		return true;
	}
}